from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.executors.asyncio import AsyncIOExecutor
import time
import aiohttp
import subprocess
import os
from pathlib import Path

from server.Base import BaseServer
import models.admin.system.Task as TaskModel
from server.Base import BaseServer


# 获取当前文件的父目录，直到项目根目录
project_root = Path(__file__).parent.parent.parent  # 根据文件层级调整 .parent 的次数
ssh_script_root = project_root / "ssh_script"  # 项目根目录下的 ssh_script 目录

class Task:
    def __init__(self):
        self.scheduler = AsyncIOScheduler()
        self.scheduler.add_executor(AsyncIOExecutor())
    
    async def start(self):
        await self.load_all_task()
        self.scheduler.start()
    async def shutdown(self):
        self.scheduler.shutdown()

    async def load_all_task(self):
        tasks = await BaseServer(TaskModel.task_job).all()
        for task in tasks:
            # 判断任务是否开启状态
            if task["status"] == TaskModel.StatusTypeEnum.NORMAL:
                await self.create_task_job(TaskModel.task_job(**task))

    @staticmethod
    async def task_ssh_function(name: str,id: str, role: str, content: str,  url: str, url_agent: str):
        # 执行任务
        print(f"Job {name} with ID {id},role {role}, content {content} is running at {time.strftime('%Y-%m-%d %H:%M:%S')}")
        await BaseServer(TaskModel.task_job).update({"id":id, "lastRunTime": time.time()})
        # 判断当前系统是否是windows,如果是windows,则不执行
        if os.name == 'nt':
            print('Windows system is not supported')
            result = 'Windows system is not supported'
        else:
            # 更新任务执行时间
            script_path = os.path.join(ssh_script_root, content)

            # 设置命令，根据角色决定执行方式
            command = ['sh', script_path]

            # 如果 role 不是空的，根据角色切换执行方式
            if role:
                if role == 'root':
                    # 如果是 root 角色，直接使用 sudo 运行
                    command = ['sudo'] + command
                else:
                    # 如果是其他角色，例如 www，使用 sudo -u 切换到指定用户
                    command = ['sudo', '-u', role] + command

            # 拼接脚本路径
            try:
                sh_result = subprocess.run(command, capture_output=True, text=True, check=True)
                result = sh_result.stdout
            except subprocess.CalledProcessError as e:
                result = f"Error occurred: {e.stderr}"
            except Exception as e:
                result = f"Error occurred: {str(e)}"
            
        # 添加任务执行记录
        record = {
            "job_id": id,
            "job_name": name,
            "status": 1 if 'Error' not in result else 0,
            "message": result
        }
        await Task.add_task_record(record)

    @staticmethod
    async def task_http_function(name: str,id: str, role: str, content: str,  url: str, url_agent: str):
        # 执行任务
        print(f"Job {name} with ID {id}, url {url}, url_agent {url_agent} is running at {time.strftime('%Y-%m-%d %H:%M:%S')}")
        # 更新任务执行时间
        await BaseServer(TaskModel.task_job).update({"id":id ,"lastRunTime": time.time()})

        # 引入http请求模块
        # 请求url，获取返回结果，进行记录
        # 引入http请求模块
        headers = {
            'User-Agent': url_agent  # 使用 url_agent 参数设置 User-Agent
        }

        # 引入http请求模块
        async with aiohttp.ClientSession() as http_session:
            try:
                # 请求url，获取返回结果
                async with http_session.get(url, headers=headers) as response:
                    result = await response.text()  # 可以改成 .json() 获取 JSON 数据
                    print(f"Response from {url}: {result}")

                    # 在这里可以对返回结果进行进一步处理
            except Exception as e:
                result = f"Error occurred: {str(e)}"


        # 添加任务执行记录
        record = {
            "job_id": id,
            "job_name": name,
            "status": 1 if 'Error' not in result else 0,
            "message": result
        }
        
        await Task.add_task_record(record)

    @staticmethod
    async def add_task_record(record: dict):
        await BaseServer(TaskModel.task_job_record).create(record)

    async def create_task_job(self, task:  TaskModel.task_job):
        if task.type == TaskModel.TaskTypeEnum.SHHSCRIPT:
            task_function = self.task_ssh_function
        elif task.type == TaskModel.TaskTypeEnum.HTTP:
            task_function = self.task_http_function

        args = (task.name, task.id)
        kwargs = {
            "role": task.role,
            "content": task.content,
            "url": task.url,
            "url_agent": task.url_agent
        }

        if task.triggerType == TaskModel.TriggerTypeEnum.EVERYDAY:
            self.scheduler.add_job(task_function, 'cron', hour=task.hour, minute=task.minute, second=task.second, id=task.id, args=args, kwargs=kwargs)
        elif task.triggerType == TaskModel.TriggerTypeEnum.EVERYWEEK:
            self.scheduler.add_job(task_function, 'cron', day_of_week=task.day, hour=task.hour, minute=task.minute, second=task.second, id=task.id, args=args, kwargs=kwargs)
        elif task.triggerType == TaskModel.TriggerTypeEnum.EVERY2WEEK:
            self.scheduler.add_job(task_function, 'cron', day_of_week=task.day, hour=task.hour, minute=task.minute, second=task.second, id=task.id, args=args, kwargs=kwargs, coalesce=True, misfire_grace_time=3600)
        elif task.triggerType == TaskModel.TriggerTypeEnum.EVERYMONTH:
            self.scheduler.add_job(task_function, 'cron', day=task.day, hour=task.hour, minute=task.minute, second=task.second, id=task.id, args=args, kwargs=kwargs)
        elif task.triggerType == TaskModel.TriggerTypeEnum.INTERVALHOUR:
            self.scheduler.add_job(task_function, 'interval', hours=task.hour, id=task.id, args=args, kwargs=kwargs)
        elif task.triggerType == TaskModel.TriggerTypeEnum.INTERVALMINUTE:
            self.scheduler.add_job(task_function, 'interval', minutes=task.minute, id=task.id, args=args, kwargs=kwargs)
        elif task.triggerType == TaskModel.TriggerTypeEnum.INTERVAL:
            self.scheduler.add_job(task_function, 'interval', seconds=task.second, id=task.id, args=args, kwargs=kwargs)
    
TaskManager = Task()